﻿namespace StockSharp.Media;

using System;
using System.Collections.Immutable;
using System.Linq;
using System.Text;
using System.IO;

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;

[Generator]
public class MediaNamesGenerator : IIncrementalGenerator
{
	private const string _typeName = "MediaNames";

	private static readonly DiagnosticDescriptor _noIconsFoundWarning = new(
		id: "MEDIA001",
		title: "No media icons found",
		messageFormat: "No PNG or SVG resources found in the logos directory",
		category: nameof(MediaNamesGenerator),
		DiagnosticSeverity.Warning,
		isEnabledByDefault: true);

#if DEBUG
	private static readonly DiagnosticDescriptor _debugInfo = new(
		id: "MEDIA002",
		title: $"{nameof(MediaNamesGenerator)} Debug Info",
		messageFormat: "Found fles: {0}",
		category: nameof(MediaNamesGenerator),
		DiagnosticSeverity.Info,
		isEnabledByDefault: true);
#endif

	void IIncrementalGenerator.Initialize(IncrementalGeneratorInitializationContext context)
	{
		var logoFiles = context.AdditionalTextsProvider
			.Where(file =>
				file.Path.EndsWith(".png", StringComparison.OrdinalIgnoreCase) ||
				file.Path.EndsWith(".svg", StringComparison.OrdinalIgnoreCase))
			.Select((file, _) => Path.GetFileName(file.Path))
			.Collect();

		context.RegisterSourceOutput(logoFiles, (spc, files) => Execute(spc, files));
	}

	private void Execute(SourceProductionContext context, ImmutableArray<string> iconFiles)
	{
#if DEBUG
		context.ReportDiagnostic(Diagnostic.Create(_debugInfo, Location.None, string.Join(";", iconFiles)));
#endif

		if (iconFiles.IsEmpty)
		{
			context.ReportDiagnostic(Diagnostic.Create(_noIconsFoundWarning, Location.None));
			return;
		}

		var source = GenerateMediaNamesSource(iconFiles);
		context.AddSource($"{_typeName}.g.cs", SourceText.From(source, Encoding.UTF8));
	}

	private string GenerateMediaNamesSource(ImmutableArray<string> iconFiles)
	{
		var sb = new StringBuilder();

		sb.AppendLine("// <auto-generated/>");
		sb.AppendLine($"// Generated by {nameof(MediaNamesGenerator)}");
		sb.AppendLine();
		sb.AppendLine("namespace StockSharp.Media;");
		sb.AppendLine();
		sb.AppendLine($"static partial class {_typeName}");
		sb.AppendLine("{");

		foreach (var iconFile in iconFiles.OrderBy(f => f))
		{
			var propertyName = SanitizePropertyName(iconFile);

			sb.AppendLine("\t/// <summary>");
			sb.AppendLine($"\t/// Gets the file name for the {propertyName} icon.");
			sb.AppendLine("\t/// </summary>");
			sb.AppendLine($"\tpublic const string {propertyName} = \"{iconFile}\";");
			sb.AppendLine();
		}

		sb.AppendLine("}");

		return sb.ToString();
	}

	private string SanitizePropertyName(string iconFile)
	{
		var name = Path.GetFileNameWithoutExtension(iconFile);

		if (name.EndsWith("_logo", StringComparison.OrdinalIgnoreCase))
			name = name.Substring(0, name.Length - "_logo".Length);

		return name.ToLowerInvariant();
	}
}